package top.glkj.hms.entity;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import top.glkj.hms.utils.StaticValue;
import top.glkj.hms.utils.Status;

import javax.persistence.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户表，实现UserDetails管理用户
 *
 * @author : xgl
 * @version : 0.0.1
 * @date :2020/11/1 0:07
 */
@Getter
@Setter
@Table(name = "hms_user")
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class User extends BaseEntity implements UserDetails {

    /**
     * 用户名
     */
    @Column(unique = true, nullable = false, length = StaticValue.FORTY)
    private String username;

    /**
     * 密码
     */
    @Column(nullable = false)
    private String password;

    /**
     * 手机
     */
    @Column(nullable = false)
    private String phone;

    /**
     * 最后一次登录时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date lastLoginTime;

    /**
     * 最后一次登录ip地址
     */
    @Column(name = "last_login_ip")
    private String lastLoginIp;

    /**
     * 最后一次登录设备
     */
    @Column(name = "last_login_client")
    private String lastLoginClient;

    /**
     * 状态码
     */
    private Status status;
    /**
     * 登录次数
     */
    private long count;


    //public void serCreateUser(User createUser){
    //    createUser.serCreateUser(new User());
    //    this.createUser = createUser;
    //}
    //
    //public User getCreateUser(){
    //    createUser.setCreateUser(new User());
    //    return createUser;
    //}

    /**
     * 用户详细信息
     */
    @Fetch(FetchMode.JOIN)
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_detail_id", referencedColumnName = "id")
    private UserDetail userDetail;
    /**
     * 拥有角色
     */
    @Fetch(FetchMode.SELECT)
    @ManyToMany(targetEntity = Role.class, cascade = CascadeType.ALL)
    @JoinTable(name = "hms_users_roles",
            //当前对象在中间表中的外键
            joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
            //对方对象在中间表中的外键
            inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}
    )
    private Set<Role> roles = new HashSet<>();

    //public Set<Role> getRoles() {
    //    if (this.roles.isEmpty()){
    //        this.roles.add(StaticValue.EMPTY_ROLE);
    //    }else if (this.roles.size()>1){
    //        this.roles.remove(StaticValue.EMPTY_ROLE);
    //    }
    //    return roles;
    //}
    //
    //public void setRoles(Set<Role> roles) {
    //    if (roles ==StaticValue.NULL||roles.isEmpty()){
    //        this.roles = new HashSet<>();
    //        this.roles.add(StaticValue.EMPTY_ROLE);
    //    }else {
    //        this.roles = roles;
    //    }
    //}

    public User(Long id) {
        super(id);
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        String permission = getRoles().stream()
                .filter(role -> role != StaticValue.NULL)
                .map(role ->
                        {
                            role.setRoleCode("ROLE_" + role.getRoleCode().toUpperCase());
                            return role.getRoleCode();
                        }
                ).
                        collect(Collectors.toSet())
                .stream()
                .filter(role -> role != StaticValue.NULL)
                .map(String::valueOf)
                .collect(Collectors.joining(",")) + getRoles().stream()
                .filter(role -> role != StaticValue.NULL && !role.getPermissions().isEmpty())
                .map(Role::getPermissions)
                .collect(Collectors.toSet())
                .stream()
                .filter(role -> role != StaticValue.NULL && !role.isEmpty())
                .map(Set::iterator)
                .collect(Collectors.toSet())
                .stream()
                .filter(role -> role != StaticValue.NULL)
                .map(Iterator::next)
                .collect(Collectors.toSet())
                .stream()
                .filter(role -> role != StaticValue.NULL)
                .map(Permission::getPermissionCode)
                .collect(Collectors.toSet())
                .stream()
                .filter(role -> role != StaticValue.NULL)
                .map(p -> "PERMISSION_" + p.toUpperCase())
                .collect(Collectors.joining(","));

        return AuthorityUtils.commaSeparatedStringToAuthorityList(permission);
    }
    @Override
    public boolean isAccountNonExpired() {
        Date endTime = this.lastLoginTime;
        if (endTime == null) {
            endTime = getCreateTime();
        }
        return ((((System.currentTimeMillis() - endTime.getTime()) / (24 * 60 * 60 * 1000))) / 365) <= 3;
    }
    @Override
    public boolean isAccountNonLocked() {
        return !status.equals(Status.Lock);
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return !status.equals(Status.NoPassWord);
    }
    @Override
    public boolean isEnabled() {
        return status.equals(Status.Enable);
    }


}
